#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cassert>
#include <cerrno>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
class ServerTcp
{
public:
    ServerTcp(uint16_t port,const std::string& ip = "")
        :port_(port),ip_(ip),listenSock_(-1)
        {
            quit_ = false;
        }
    ~ServerTcp()
    {
        if(listenSock_>= 0)
        {
            close(listenSock_);
        }
    }
public:
    void init()
    {
        //1.创建socket
        listenSock_ = socket(PF_INET,SOCK_STREAM,0);
        if(listenSock_ < 0) exit(1);
        int opt = 1;
        setsockopt(listenSock_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        //2.bind 绑定
        //填充服务器信息
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = PF_INET;
        local.sin_port = htons(port_);
        ip_.empty()?(local.sin_addr.s_addr = INADDR_ANY):(inet_aton(ip_.c_str(),&local.sin_addr));
       
        if(bind(listenSock_,(const struct sockaddr*)&local,sizeof(local)) < 0) 
        {
            std::cerr<<"bind error" <<std::endl;
            exit(2);
        }
        //3.监听
        if(listen(listenSock_,2) < 0) exit(3);
        //让别人来链接你
    }
    void loop()
    {
        signal(SIGCHLD,SIG_IGN);//only linux
        while(!quit_)
        {
            sleep(1);
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);

            int serviceSock = accept(listenSock_,(struct sockaddr *)&peer,&len);
            if(quit_) break;
            if(serviceSock<0)
            {
                //获取链接失败
                std::cerr<<"accept error........." <<std::endl;
                continue;
            }
            std::cout<<"获取新链接成功： "<<std::endl;
        }
    }

    bool quitServer()
    {
        quit_ = true;
        return true;
    }

private:
    int listenSock_;
    uint16_t port_;
    std::string ip_;
    bool quit_;//安全退出
};